跳到主要内容

1.3-运算符

Create by fall on 14 Sep 2021 Recently revised in 27 Jun 2023

算术运算符

和其他语言一样,所以我这里只是列出来

  • + 对数字进行求和,或者是拼接字符串
  • - 对数字取负值,或者进行相减
  • * 乘法运算
  • / 除法运算
  • % 取余运算

一些特殊的运算符

  • ** 表示次方运算

自增自减

自增自减会根据位置,决定是先运算还是先输出

  • -- 表示递减操作
  • ++ 表示递增操作

关系运算符

  • > 大于,>= 大于等于
  • < 小于,<= 小于等于
  • == 等于
  • === 严格等于
  • != 表示不等于
1== true // true
5 == true // false
1 === true // false

位运算符

  • & 按位与运算
  • ^ 按位异或运算符
  • | 按位或运算符
  • ~ 按位非运算符
7|11 // 7 按位运算,结果为 15
// 7 转换为二进制是 111 ,11 转换为二进制是 1011
// 0111
// 1011
// 每一位进行 或 运算,得到结果为
// 1111 // 转为十进制为 15
3&2 // 2
7^11
// 7 的二进制为 111,11 的二进制为 1011
// 0111
// 1011
// 1100 这是异或后结果,也就是 12
// 按位非
~5 // -6
// 00000000000000000000000000000101
// 11111111111111111111111111111010
  • >> 按位进行,向右移动
  • << 按位进行向左移动,左边超出的位数将会被清除
  • >>> 无符号右移,也称作零填充右移(忽略最开始的符号位)
// >> 右移运算
4 >> 2 // 2
-4 >> 2
// << 左移运算
1<<2 // 4
-1 << 2 // -4

// 无符号右移
const a = 5; // 00000000000000000000000000000101
console.log(a >>> 2); // 00000000000000000000000000000001
// Expected output: 1
const c = -5; // 11111111111111111111111111111011
console.log(c >>> 2); // 00111111111111111111111111111110
// Expected output: 1073741822

注:没有无符号左移

逻辑运算符

基本运算符

  • 与运算符 &&
  • 或运算符 ||
  • 非运算符 !
  • 空值合并运算符 ??
// 与运算符的赋值
const state = true
const content = '这里是一些内容'
const result1 = state && content
const result2 = content && state
// 与运算符也会返回第一个为 false 的内容,如果没有为 false 的内容,返回最后一个
result1 // '这里是一些内容'
result2 // true
// 或运算符的赋值
const result3 = true || '996'
const result4 = false || '996'

运算符的简写

x &&=y 相当于 x && (x=y)

x ||=y 相当于 x || (x=y)

x ??=y 相当于 x ?? (x=y)

let x = 0
x &&=9 // 0
x ||=12 // 12
x ??=55 // 0

空值合并运算符

?? 两个问号

用于解决 || 运算符无法应对的情况,|| 中,只要转成 Boolean 后是 false,左侧的值就会被忽略

let age = 0 || 20
age // 20
let age = '' || null

空值合并预算符只有左侧为 null 或者 undefined 会取右侧的值

let age = 0 ?? 20
age // 0

三步运算符

let x = 10
x>0?x=999:x='wtf'
x // 999
x = x>0?-x:x
x // -999

逗号运算符

会对每个操作数从左到右求值,并返回最后一个操作数的值。

let foo = (2, 3);
foo // 3
// 在三步运算符中指定操作,和返回值时使用
let list = [99,66,88]
let newlist = list.indexOf(70) == -1 ? ( list.push( v ), list ) : list

括号运算符

let x = ( 2 + 20 ) * 20
// 440

可选链操作符

ES2020 中新增的特性

obj.name?.

let obj = {
name:{
firstName:'zhang'
}
}
obj.name.firstName // 一般是这样取值,但是如果不存在 name 无法取值并且报错
// 为了防止报错通常采用以下两种方法
// 1. 使用 if 进行判断
if(obj){
if(obj.name){
let name1 = obj.name.firstName
}
}
// 2.利用 && 运算符的特性
let name2 = obj && obj.name && obj.firstName
// 用了该符号,一次性解决
let name3 = obj?.name?.firstName

操作符关键字

delete

const Employee = {
firstname: 'John',
lastname: 'Doe'
};
console.log(Employee.firstname);
// Expected output: "John"
delete Employee.firstname;
// delete Employee['firstname']
console.log(Employee.firstname);
// Expected output: undefined

in

可以使用 for...in 对对象进行遍历

let obj = {
name:'fall',
age:24
}
// msg 为 obj 的 name、age
for(let msg in obj){
console.log(msg)
}
console.log('name' in obj) // true

new

class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A { constructor() { super(); } }

var a = new A(); // logs "A"
var b = new B(); // logs "B"
class C { constructor() { console.log(new.target); } }
class D extends C { constructor() { super(); } }
var c = new C(); // logs class C{constructor(){console.log(new.target);}}
var d = new D(); // logs class D extends C{constructor(){super();}}

instanceof

用于判断某个类是不是另一个类继承的

Array instanceof Object 
// true

typeof

用于判断数据的类型

typeof 2 // 'number'
typeof 'fall' // 'string'
typeof false // 'boolean'
typeof [] // 'object'

super

待补充

数值分隔符

_ 可以将数字分割,进行声明,方便查看,可以用于多种进制

注:两侧必须都要有数值

let num = 3146_46446
let num1 = 31_n // error 错误书写格式
let num2 = 0x_664 // error 错误书写格式

展开运算符

Spread syntax,可以进行扩展

Math.max(...[1,2,3]) // 3

对象中的应用

可以应用在解构赋值,但是只能应用在最后一个变量上,被接受的值会直接赋值过去,没被接受的会全部复制到展开运算符后的声明数中

let {fall, ...y} = {dear:'55',fall:'23',b:'2',c:3}
y // {b:'2',c:3}

实现对象的合并

let a = {name:'fall'}
let b = {age:'23'}
let info = {...a,...b}
info //{ name: "fall", age: "23" }

数组中的应用

数组的解构赋值

let [a, b, c = 'c'] = '12'
console.log(a, b, c) // '1' '2' 'c'

解构

解构数组

// 结构数组的声明
var [x,y,z] = [10,22,33]
console.log(x+'----'+z )
var [x,y,[a,b],z] =[11,22,[],33]
// 结构函数的声明
var {toFixed:ss} = 1000
// 实际上 此时 ss === Number.prototype.toFixed

解构对象

const {age} = {name:'fall',age:21}
age // 21
// 解构对象上的方法
// 获取到 10 上的 toFixed 方法,并将该方法赋给 tf,任意数值都可以通过解构获取到原型对象上的方法
let {toFixed: tf} = 10
tf.call(Math.PI, 2) // 3.14 // 使用 call 改变指针指向,call 方法读取的是 this 来执行的

解构名称转换

const {a:megic} = {a:'close your eyes'}
megic // 'close your eyes'

解构默认赋值

const {a=10,b=100} = {a:36}

解构的用途

// 1. 交换变量的值
var [a,b] = [11,22];
[a,b] = [b,a];
alert(a+' and '+b);
// 2. 可以返回多个变量的值
function etc(){
return ['acj','txt','fbi'];
}
var [r1,r2,r3] =etc()
// 3.解决必须通过固定格式书写的问题
// 参数可以传入默认值
// 固定格式书写
function file(name,age,gender){
alert('我叫'+name+',今年'+age+'岁,性别是'+gender);
}
file('小明',55,'男');
// 非固定格式书写
function file({name,age,gender = 'boy'}){
alert('我叫'+name+',今年'+age+'岁,性别是'+gender);
};
file({
name:'小明',
gender:'男',
age:22,
})
// 注,至少传入一个对象才能成功地调用方法
file({})
// 4.快速取出数组
var arr = [11,22,33,44,55];
var {0:first,4:last} = arr;
alert(first);
alert(last == arr[4]);

获取数据类型上的方法

let {toFixed: tf} = 10
// 获取到 10 上的 toFixed 方法,并将该方法赋给 tf
console.log(tf.call(Math.PI, 2)) // 3.14

布尔值解构

let {toString: ts} = true
console.log(ts.call(false)) // 'false'

数组解构:等号右侧的数据具有 Iterator 接口可以进行数组形式的解构赋值;

// 解构不成功的变量值为 undefined
let [a, b, c] = [1, 2]
console.log(a, b, c) // 1, 2, undefined

// 可以设置默认值
let [x, y, z = 3] = [1, 2, null]
console.log(x, y, z) // 1, 2, null

什么样的数据具有 Iterator 接口呢?如果一个对象能够通过 [Symbol.iterator] 访问,且能够返回一个符合迭代器协议的对象,那么该对象就是可迭代的。目前内置的可迭代对象有:String、Array、TypeArray、Map、Set、arguments 和 NodeList 等。

  • 对象解构:与数组按照索引位置进行解构不同,对象解构是按照属性名进行解构赋值,如果在当前对象属性匹配不成功则会去对象的原型属性上查找:
// 默认写法
let { name: name, age: age } = { name: '布兰', age: 12 }
// 简写
let { name, age } = { name: '布兰', age: 12 }
// 改名且设置默认值
let { name: name1, age: age1 = 12 } = { name: '布兰' }
console.log(name1, age1) // '布兰' 12
  • 函数参数解构:其实就是运用上面的对象解构和数组解构规则;

    function move({x = 0, y = 0} = {}) {
    console.log([x, y])
    return [x, y];
    }
    move({x: 3, y: 8}) // [3, 8]
    move({x: 3}) // [3, 0]
    move({}) // [0, 0]
    move() // [0, 0]

解构要点

  • 只要等号两边的模式相同(同是对象或同是数组),则左边的变量会被赋予对应的值;
  • 解构不成功的变量值为 undefined
  • 默认值生效的前提是当等号右边对应的值全等于 undefined 的时候;
  • 只要等号右边的值不是对象或者数组,则会进行自动装箱将其转成对象;
  • nullundefined 都无法转成对象,所以无法解构。

解构应用

  • 交换变量的值;

    let x = 1, y = 2;
    // 交换时,不要对 x、y 的值进行操作
    [x, y] = [y, x]
    console.log(x, y) // 2 1
  • 通过函数返回对象属性

    function getParams() {
    return {
    name: '布兰',
    age: 12,
    }
    }
    let {name, age} = getParams()
  • 通过定义函数参数来声明变量

    let person = {
    name: '布兰',
    age: 12
    }
    init(person)

    // 普通用法
    function init(person) {
    let {name, age} = person
    }

    // 更简洁用法
    function init({name, age}) {}
  • 指定函数参数默认值

    function initPerson({name = '布兰', age = 12} = {}) {
    console.log(name, age)
    }
    initPerson() // '布兰' 12
    initPerson({age: 20}) // '布兰' 20
  • 提取 JSON 数据

    let responseData = {
    code: 1000,
    data: {msg:'来了来了'},
    message: 'success'
    }
    // 这里面的 data 为默认值
    let { code, data = {} } = responseData
  • 遍历 Map 结构

    let map = new Map()
    map.set('beijing', '北京')
    map.set('xiamen', '厦门')

    for (let [key, value] of map) {
    console.log(key, value)
    }
  • 输入模块的指定方法和属性

    const { readFile, writeFile } = require("fs")

参考文章

文章名称链接
「建议收藏」送你一份精心总结的3万字ES6实用指南(上)https://juejin.cn/post/6895898051559456776#heading-6
MDN 官方文档https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators